home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-05-30 | 6.8 KB | 271 lines | [TEXT/ttxt] |
- // This may look like C code, but it is really -*- C++ -*-
- /*
- ************************************************************************
- *
- * Grayscale Image
- *
- * Write the image into the file in the X11 Window dump format
- * and display it with xwud program
- *
- * $Id: write_xwd.cc,v 2.0 1995/03/09 15:24:11 oleg Exp oleg $
- *
- ************************************************************************
- */
-
- #include "image.h"
- #include "endian_io.h"
- #ifdef __GNUC__
- #pragma implementation "x11wd.h"
- #endif
- #include "x11wd.h"
-
-
- /*
- *------------------------------------------------------------------------
- * Writing of X11 WD data structures
- */
-
- void X11XColor::write(EndianOut& outs) const
- {
- outs.write_long ( pixel );
- outs.write_short( red );
- outs.write_short( green );
- outs.write_short( blue );
- outs.write_byte ( flags );
- outs.write_byte ( pad );
- }
-
- void X11XColor::write_gray_colormap(EndianOut& outs, const int ncolors)
- {
- for(register int i = 0; i < ncolors; i++)
- {
- X11XColor grayshade(i, ncolors == 256 ? ((long)i<<8) | i :
- (((long)i<<16)-i)/(ncolors-1) );
- grayshade.write(outs);
- }
- }
-
- /*
- *------------------------------------------------------------------------
- * Class XWdump
- * designed to contain the control info about the image
- * as defined in the X Window Dump file
- */
-
- class XWdump // All the info pertaining to the XWD file
- : public X11WDFileHeader, public EndianOut {
-
- private:
- const IMAGE& image; // Image being processed
- const char * title; // Title for the image in the file
-
- void write_image_data(void);
-
- public:
- XWdump(const IMAGE& _image); // Constructor
- void set_title(const char * user_title);
- void write_image(const char * file_name);
- };
-
- /*
- *------------------------------------------------------------------------
- * Construct the XWdump
- * by filling out the fields of the structure from the IMAGE
- */
-
- XWdump::XWdump(const IMAGE& _image) : image(_image)
- {
- title = image.q_name();
- assure(image.q_depth() <= 8,
- "Sorry, the program cannot write images with depth > 8");
-
- header_size = sizeof(X11WDFileHeader) + strlen(title) + 1;
- file_version = X11WD_FILE_VERSION;
- pixmap_format = ZPixmap;
- pixmap_width = image.q_ncols();
- pixmap_height = image.q_nrows();
- xoffset = 0;
- xbyte_order = MSBFirst; set_bigendian();
- bitmap_bit_order = MSBFirst;
- window_width = image.q_ncols();
- window_height = image.q_nrows();
- window_x = 0;
- window_y = 0;
- window_bdrwidth = 0;
-
- pixmap_depth = 8;
- bits_per_pixel = 8;
- colormap_entries = 256;
- ncolors = 256;
- bytes_per_line = image.q_ncols();
-
- bitmap_unit = 8;
- bitmap_pad = 8;
- visual_class = StaticGray;
- red_mask = 0;
- green_mask = 0;
- blue_mask = 0;
-
- bits_per_rgb = pixmap_depth;
- }
-
- /*
- *------------------------------------------------------------------------
- * Set up the title for the image
- * image.name == "" && user title == "" ---> resulting title = ""
- * image.name != "" && user title == "" ---> resulting title = image.name
- * image.name == "" && user title != "" ---> resulting title = user title
- * image.name != "" && user title != "" --->
- * resulting title = "image name/user title"
- *
- * Note that XWdump::title has been already set to image.title.
- * If it is changed, the XWdump::header_size should be modified as well
- */
-
- void XWdump::set_title(const char * user_title)
- {
- if( strlen(user_title) == 0 )
- return;
-
- register int old_title_len = strlen(title);
-
- if( strlen(title) == 0 ) // No image title
- title = user_title;
- else
- title =
- strcat(
- strcat(
- strcpy((char *)calloc(strlen(title)+1+strlen(user_title)+1,
- sizeof(char)),title),
- "/"),
- user_title);
-
- header_size += strlen(title) - old_title_len;
- }
-
- /*
- *------------------------------------------------------------------------
- * Writing the X window dump file
- */
-
- void XWdump::write_image(const char * file_name)
- {
-
- open(file_name);
- // Writing the header
- write_long( header_size );
- write_long( file_version );
- write_long( pixmap_format );
- write_long( pixmap_depth );
- write_long( pixmap_width );
- write_long( pixmap_height );
- write_long( xoffset );
- write_long( xbyte_order );
- write_long( bitmap_unit );
- write_long( bitmap_bit_order );
- write_long( bitmap_pad );
- write_long( bits_per_pixel );
- write_long( bytes_per_line );
- write_long( visual_class );
- write_long( red_mask );
- write_long( green_mask );
- write_long( blue_mask );
- write_long( bits_per_rgb );
- write_long( colormap_entries );
- write_long( ncolors );
- write_long( window_width );
- write_long( window_height );
- write_long( window_x );
- write_long( window_y );
- write_long( window_bdrwidth );
-
- write(title, strlen(title)+1); // Write out the dump name
- X11XColor::write_gray_colormap(*this,ncolors);
- write_image_data();
-
- close();
- }
-
- /*
- *------------------------------------------------------------------------
- * Write out the pixel matrix
- * with 'bits_per_pixel'representation
- */
-
- void XWdump::write_image_data(void)
- {
- register card row, col;
- const long int maxval = (1 << image.q_depth()) - 1;
- const long int bigger_maxval = (1 << bits_per_pixel) - 1;
-
- assure(maxval <= bigger_maxval,
- "Cannot display image with too many bits per pixel");
-
- // Using simplified procedure if possible
- if( bits_per_pixel == 8 && image.q_depth() == 8 )
- {
- for( row = 0; row < pixmap_height; ++row )
- for( col = 0; col < pixmap_width; ++col )
- write_byte( image(row,col) );
- return;
- }
-
- // Handle the general case if tricks don't
- // work
- for( row = 0; row < pixmap_height; ++row )
- {
- register int bitshift = 8 - bits_per_pixel;
- register char byte = 0;
-
- for( col = 0; col < pixmap_width; ++col )
- {
- register long s = image(row,col);
-
- if( maxval != bigger_maxval )
- s = (((long)s << bits_per_pixel)-s) / maxval;
- byte |= s << bitshift;
- bitshift -= bits_per_pixel;
- if( bitshift < 0 )
- {
- write_byte( byte );
- bitshift = 8 - bits_per_pixel;
- byte = 0;
- }
- if( bitshift < 8 - (signed)bits_per_pixel )
- write_byte( byte );
- }
- }
- }
-
-
- /*
- *------------------------------------------------------------------------
- * Root modules
- * for writing the image and displaying it
- */
-
- void IMAGE::write_xwd(const char * file_name,const char * title) const
- {
- is_valid();
-
- message("\nPreparing XWD file with name '%s'\n",file_name);
- XWdump XWdump(*this);
- XWdump.set_title(title);
- XWdump.write_image(file_name);
- }
-
- #ifndef __MWERKS__
- // Display the image with 'xwud' program
- void IMAGE::display(const char * title) const
- {
- register int kid_id; // ID of the kid process
- if( getenv("DISPLAY") == (char *)0 ) // Bypass if isn't an X terminal
- return;
- assert( (kid_id = fork()) != -1 );
- if( kid_id == 0 ) // We're in the kid process
- {
- write_xwd("| xwud",title);
- exit(0);
- }
- }
- #endif